#include "stdafx.h"
#include "../3ds/io/io3ds.h"
#include "render/rendermgr.h"
#include "game/gamemgr.h"
#include "./pixelbutton.h"

#define NORMAL "_normal.jpg"
#define HOVER "_hover.jpg"
#define DOWN "_down.jpg"

PixelButton::PixelButton(string strName, Point pos, float z)
: m_pos(pos)
, m_z(z)
, m_status(ButtonStatus_Normal)
, m_width(0)
, m_height(0)
, m_bDown(false)
, m_bEnable(true)
{
	m_texNormal = LoadFile(strName + NORMAL);
	m_texHover = LoadFile(strName + HOVER);
	m_texDown = LoadFile(strName + DOWN);

	Size winSize = GameMgr::GetInstance().GetWinSize();
	m_width = m_biSize.cx * 100 / (float)winSize.cx;
	m_height = m_biSize.cy * 100 / (float)winSize.cy;

	RenderMgr::GetInstance().OnRender += EventObject<OnRenderFunc>(this, &PixelButton::OnRender);
}

PixelButton::~PixelButton()
{
	RenderMgr::GetInstance().OnRender -= EventObject<OnRenderFunc>(this, &PixelButton::OnRender);
	glDeleteLists(m_texNormal, 1);
	glDeleteLists(m_texDown, 1);
	glDeleteLists(m_texHover, 1);
}

void PixelButton::SetEnable(bool e)
{
	m_bEnable = e;
	if (!m_bEnable)
	{
		m_status = ButtonStatus_Normal;
	}
}

unsigned int PixelButton::LoadFile(string strPath)
{
	unsigned int texid = -1;

	ImageData imagedata = GetImageData(strPath);
	if (imagedata.bSucceeded)
	{
		texid = GetDrawList(imagedata);
		m_biSize = Size(imagedata.nWidth, imagedata.nHeight);
	}
	imagedata.ReleaseBuffer();

	return texid;
}

ImageData PixelButton::GetImageData(string strJpegPath)
{
	ImageData data;

	size_t jpegsize = IO3ds::GetInstance().ReadFile(strJpegPath, NULL, 0);
	byte* buffer = new byte[jpegsize];

	size_t rb = IO3ds::GetInstance().ReadFile(strJpegPath, buffer, jpegsize);
	if (rb != jpegsize)
	{
		data.bSucceeded = false;
		return data;
	}

	JpegDecoder decoder(buffer, rb);
	data = decoder.GetImageData();

	delete[] buffer;
	return data;
}

unsigned int PixelButton::GetDrawList(ImageData& data)
{
	unsigned int texid = glGenLists(1);
	glNewList(texid, GL_COMPILE);
	glPushMatrix();
	glTranslatef(0, 0, m_z);
	glRasterPos2f(m_pos.x, m_pos.y);
	glDrawPixels(data.nWidth, data.nHeight, GL_RGBA, GL_UNSIGNED_BYTE, data.pBuffer);
	glPopMatrix();
	glEndList();

	return texid;
}

void PixelButton::OnRender(float differTime)
{
	if (!m_bVisible)
		return;

	switch (m_status)
	{
	case ButtonStatus_Normal:
		glCallList(m_texNormal);
		break;
	case ButtonStatus_Hover:
		glCallList(m_texHover);
		break;
	case ButtonStatus_Down:
		glCallList(m_texDown);
		break;
	}
}

void PixelButton::FireOnClickEvent()
{
	RenderMgr::GetInstance().OnExtRender -= EventObject<OnExtRenderFunc>(this, &PixelButton::FireOnClickEvent);
	FireEvent(OnButtonClickFunc, OnClick, ());
}

bool PixelButton::HitTest(Point curPos)
{
	if (curPos.x < m_pos.x || curPos.y < m_pos.y ||
		curPos.x > m_pos.x + m_width || curPos.y > m_pos.y + m_height)
	{
		return false;
	}

	return true;
}

void PixelButton::OnMouseMove(Point pos)
{	
	if (!m_bEnable || !m_bVisible)
		return;

	if (HitTest(pos))
	{
		m_status = m_bDown ? ButtonStatus_Down : ButtonStatus_Hover;
	}
	else
	{
		m_bDown = false;
		m_status = ButtonStatus_Normal;
	}
}

void PixelButton::OnMouseLButtonDown(Point pos)
{
	if (!m_bEnable || !m_bVisible)
		return;

	if (HitTest(pos))
	{
		m_bDown = true;
		m_status = ButtonStatus_Down;
	}
	else
	{
		m_status = ButtonStatus_Normal;
	}
}

void PixelButton::OnMouseLButtonUp(Point pos)
{
	if (!m_bEnable || !m_bVisible)
		return;

	if (HitTest(pos))
	{
		m_status = ButtonStatus_Hover;
		if (m_bDown)
		{
			RenderMgr::GetInstance().OnExtRender += EventObject<OnExtRenderFunc>(this, &PixelButton::FireOnClickEvent);
		}
	}
	else
	{
		m_status = ButtonStatus_Normal;
	}

	m_bDown = false;
}